package hcj

// 自定义的函数
import (
	"flag"
	"fmt"
	"math"
	"sync"
)

func MathTest() {
	minInt8 := math.MinInt8
	maxInt8 := math.MaxInt8
	fmt.Printf("最小值int8 %d \n", minInt8)
	fmt.Printf("最大值int8 %d \n", maxInt8)
	fmt.Printf("最大值float %f \n", math.MaxFloat32)
}

func PointTest() {
	// 准备一个字符串类型
	var house = "Malibu Point 10880, 90265"
	// 对字符串取地址, ptr类型为*string
	ptr := &house
	// 打印ptr的类型
	fmt.Printf("ptr type: %T\n", ptr)
	// 打印ptr的指针地址
	fmt.Printf("address: %p\n", ptr)
	// 对指针进行取值操作
	value := *ptr
	// 取值后的类型
	fmt.Printf("value type: %T\n", value)
	// 指针取值后就是指向变量的值
	fmt.Printf("value: %s\n", value)
	// 使用new创建指针
	pInt8 := new(int8)
	fmt.Println("使用new关键字创建指针 pStr的默认值为:", *pInt8)
}

// 交换函数
func Swap(a, b *int) {
	fmt.Println("交换前a和b指针对应的值", *a, *b)
	// 取a指针的值, 赋给临时变量t
	t := *a
	// 取b指针的值, 赋给a指针指向的变量
	*a = *b
	// 将a指针的值赋给b指针指向的变量
	*b = t
	fmt.Println("交换后a和b指针对应的值", *a, *b)
}

// CmdTest 命令行参数
func CmdTest() {
	// 定义命令行参数
	var mode = flag.String("mode", "", "process mode")
	flag.Parse()
	fmt.Println("命令行参数--mode的值为：", *mode)
}

func ArrayCopyTest() {
	// 设置元素数量为1000
	const elementCount = 1000
	// 预分配足够多的元素切片
	srcData := make([]int, elementCount)
	// 将切片赋值
	for i := 0; i < elementCount; i++ {
		srcData[i] = i
	}
	// 引用切片数据
	refData := srcData
	// 预分配足够多的元素切片
	copyData := make([]int, elementCount)
	// 将数据复制到新的切片空间中
	copy(copyData, srcData)
	// 修改原始数据的第一个元素
	srcData[0] = 999
	// 打印引用切片的第一个元素
	fmt.Println(refData[0])
	// 打印复制切片的第一个和最后一个元素
	fmt.Println(copyData[0], copyData[elementCount-1])
	// 复制原始数据从4到6(不包含)
	copy(copyData, srcData[4:6])
	for i := 0; i < 5; i++ {
		fmt.Printf("%d ", copyData[i])
	}
}

// MapCommonTest Map读写
func MapCommonTest() {
	var myMap map[string]interface{}
	myMap = make(map[string]interface{})
	myMap["key_a"] = "value_a"
	myMap["key_b"] = "value_b"
	// map遍历
	for key := range myMap {
		fmt.Println("key=", key, myMap[key])
	}
	// 元素是否存在
	key_c, isExists := myMap["key_c"]
	fmt.Println(key_c, isExists)
	key_a, isExists := myMap["key_a"]
	fmt.Println(key_a, isExists)
	// 元素移除
	delete(myMap, "key_c")
	// map遍历
	for key := range myMap {
		fmt.Println("key=", key, myMap[key])
	}
}

// MapTest 异步Map读写(多线程使用，防止锁竞争问题)
func MapTest() {
	var scene sync.Map
	// 将键值对保存到sync.Map
	scene.Store("greece", 97)
	scene.Store("london", 100)
	scene.Store("egypt", 200)
	// 从sync.Map中根据键取值
	fmt.Println(scene.Load("london"))
	// 根据键删除对应的键值对
	scene.Delete("london")
	// 遍历所有sync.Map中的键值对
	scene.Range(func(k, v interface{}) bool {
		fmt.Println("iterate:", k, v)
		return true
	})
}

// ClosureTestA 闭包测试
func ClosureTestA() {
	// 准备一个字符串
	str := "hello world"
	fmt.Printf("str初始值：%s \n", str)
	// 创建一个匿名函数
	foo := func() {
		// 匿名函数中访问str
		str = "hello dude"
		fmt.Println("匿名函数中访问str", str)
	}
	// 调用匿名函数
	foo()
}

// DefineClosure 定义一个闭包函数：提供一个值, 每次调用函数会指定对值进行累加
func DefineClosure(value int) func() int {
	// 返回一个闭包
	return func() int {
		// 累加
		value++
		// 返回一个累加值
		return value
	}
}

// ClosureTestB 闭包测试2
func ClosureTestB() {
	// 创建一个累加器, 初始值为1
	accumulator := DefineClosure(1)
	// 累加1并打印
	fmt.Println(accumulator())
	fmt.Println(accumulator())
	// 打印累加器的函数地址
	fmt.Printf("%p\n", &accumulator)
	// 创建一个累加器, 初始值为10
	accumulator2 := DefineClosure(10)
	// 累加1并打印
	fmt.Println(accumulator2())
	// 打印累加器的函数地址
	fmt.Printf("%p\n", &accumulator2)
}

// MyPrintf 可变参数
func MyPrintf(args ...interface{}) {
	for _, arg := range args {
		switch arg.(type) {
		case int:
			fmt.Println(arg, "is an int value.")
		case string:
			fmt.Println(arg, "is a string value.")
		case int64:
			fmt.Println(arg, "is an int64 value.")
		default:
			fmt.Println(arg, "is an unknown type.")
		}
	}
}

// PrintMsg 打印消息类型, 传入匿名结构体
func PrintMsg(msg *struct {
	Code string
	Msg  string
	Data interface{}
}) {
	// 使用动词%T打印msg的类型
	fmt.Printf("%T\n", msg)
}
